<?php 

/**
 * Classe responsável por fazer importação de informações de outros sistemas
 * 
 */
class Admin_Model_Importacao
{
    
    /**
     * Informações referentes as tabelas que deverão receber carga
     *
     * @var array 
     */
    private $_tabelas = array("CARENCIAS"       => array("zend" => "Carencias", "postgre" => "carencias"),
                              "EMPREGADOS"      => array("zend" => "Empregados", "postgre" => "empregados"),
                              "DISCIPLINA"      => array("zend" => "Disciplinas", "postgre" => "disciplinas"),
                              "ENDERECO"        => array("zend" => "Enderecos", "postgre" => "enderecos"),
                              "COMPLEMENTO"     => array("zend" => "EmpregadosComplementos", "postgre" => "empregados_complementos"),
                              "FUNCAO"          => array("zend" => "Funcoes", "postgre" => "funcoes"),
                              "HABILITACAO"     => array("zend" => "Habilitacoes", "postgre" => "habilitacoes"),
                              "HABILITACAO-EMP" => array("zend" => "HabilitacoesEmpregados", "postgre" => "habilitacoes_empregados"),
                              "LOTACAO"         => array("zend" => "Lotacoes", "postgre" => "lotacoes"),
                              "UA"              => array("zend" => "UnidadesAdministrativas", "postgre" => "unidades_administrativas")
                            );
    
    /**
     * Schema do banco que receberá a importação dos arquivos...
     * 
     * @var string 
     */
    private $_schema    = 'sigrh';
    
    
    /**
     * Função que irá importar informações referentes a professores.
     * 
     * @param array $data
     * @param string $tipo
     * @return array $result
     */
    public function importarArquivo($post) 
    {       
        try { 
            $dir    = APPLICATION_PATH.'/../data/carga/'; 
  
            // Salvar o arquivo no servidor
            $upload = new Zend_File_Transfer_Adapter_Http();           
            $upload->addValidator('Count', false, array('min' => 1, 'max' => 1)) 
                   ->addValidators(array('Size'  => array('min' => 1, 'max' => '30 MB'))) 
                   ->setDestination(APPLICATION_PATH.'/../data/tmp/'); 
            $files = $upload->getFileInfo();   
  
            foreach ($files as $file => $info) { 
                if ($upload->isValid($file)) { 
  
                    // Corrige o nome antes de enviar para o banco de dados e para o local especificado 
                    $ren_anexo      = new Sedf_Filter_FiltrarAnexo(); 
                    $nome_correto   = $ren_anexo->filter($info['name']); 
  
                    // Renomeando o arquivo recebido pelo sistema 
                    $upload->receive($file); 
                    $Rename = new Zend_Filter_File_Rename(array( 
                        'target'    => $dir.$nome_correto, 
                        'overwrite' => true)); 
                    $Rename->filter(APPLICATION_PATH.'/../data/tmp/'.$info['name']); 
  
                    // Descompacta o arquivo...
                    $resultDescompactacao = $this->descompactar($dir.$nome_correto, $nome_correto);
                    
                    // Verifica se houve descompactação...
                    if ($resultDescompactacao['result'] == true) {
                        
                        // Lista os arquivos da pasta descompactada e faz carga 1 a 1
                        $lstArquivos = $this->listarArquivos( $dir . strstr($nome_correto, '.', true) );
                        
                        // Da carga em cada arquivo descompactado...
                        foreach ($lstArquivos['arquivos'] as $arquivo) {                           
                            $result[] = $this->prepararCarga($dir.$resultDescompactacao['nomePasta'].'/', $arquivo);
                        }                        
                        
                    } else {
                        return $resultDescompactacao;
                    }
                    
                } else { 
                    $result = array('type'      => 'erro', 
                                    'result'    => false, 
                                    'flashMsg'  => 'Problemas no envio do arquivo'); 
                    return $result; 
                } 
            } 

        } catch (Exception $exc) { 
            $result = array('type'      => 'erro', 
                            'result'    => false,
                            'flashMsg'  => 'Problemas no envio do arquivo'); 
        } 
  
        return $result; 
    }
    
    
    /**
     * Com base no arquivo enviado e nas informações contidas o sistema deverá
     * ler o arquivo e salva-lo na base de dados.
     * 
     * @param string $dir
     * @param string $linkFile
     * @return array $result
     */
    private function prepararCarga($dir, $linkFile) 
    {
        if (file_exists($dir.$linkFile)) {
            $arquivo        = file_get_contents($dir.$linkFile);
            $arquivoArray   = explode("\n", $arquivo);
            $cabecalho      = explode("|", $arquivoArray[0]);
            $base           = str_replace('652-000-CADRMV30-REMOCAO-', '', substr($linkFile, 0, -14) );
            
            foreach ($arquivoArray as $key => $linha) {
                if ($key != 0) { //Evita ler o cabecalho novamente...
                    $conteudo[] = explode("|", $linha);
                }
            }            
            
            // Tenta inserir o conteúdo na base de dados.
            $inserido = $this->inserirConteudoNaBase(array('cabecalho' => $cabecalho, 'conteudo' => $conteudo), $base);
            
            // Verifica se todas as informações foram inseridas na base de dados.
            if ($inserido['type'] == 'success') {
                $result = array('type'      => 'success', 
                                'result'    => true,
                                'inserido'  => $inserido);
                
            } else {    
                $result = array('type'      => 'erro', 
                                'result'    => false,
                                'flashMsg'  => 'Aparentemente o arquivo foi enviando, porém não foi possível fazer a carga das informações.');
            }
            
        } else {
            $result = array('type'      => 'erro', 
                            'result'    => false,
                            'flashMsg'  => 'Aparentemente o arquivo foi enviando, porém não foi possível fazer a carga das informações.');
        }
        
        return $result;
    }
    
    
    /**
     * Depois que o arquivo estiver no servidor e estiver no formato de array
     * esta função irá salvar linha a linha as informações na base de dados.
     * 
     * @param string $arquivo
     * @param string $base
     * @return 
     */
    private function inserirConteudoNaBase($arquivo, $base) 
    {
        set_time_limit(0);
        
        try {
            $tblName = "Admin_Model_DbTable_Sigrh_". $this->_tabelas[$base]['zend'];
            $header  = implode(', ', array_map('strtolower', $arquivo['cabecalho']));
            $table = new $tblName();
            
            // Prepara o conteúdo para ser executado no banco
            foreach ($arquivo['conteudo'] as $linha) {
                if (count($linha) >= 2) {
                    $insert     = array_map('addslashes', array_map('trim', $linha));      
                    $conteudo  .= "('". implode("', '", $insert) ."'), ";
                }
            }
            
            // Prepara a string para ser executada no banco 
            $sql    = sprintf("INSERT INTO {$this->_schema}.{$this->_tabelas[$base]['postgre']} ({$header}) VALUES %s", substr($conteudo, 0, -2) );
            $stmt   = $table->getAdapter()->prepare(utf8_encode($sql));
            $stmt->execute();
            
            $result = array('type'      => 'success', 
                            'result'    => true,
                            'tabela'    => "{$this->_schema}.{$this->_tabelas[$base]['postgre']}");
            
        } catch (Exception $exc) {           
            $result = array('type'      => 'erro', 
                            'result'    => false,
                            'flashMsg'  => $exc->getMessage());
            
            Zend_Debug::dump($exc->getTraceAsString());
            die();
        }
        
        return $result;
    }
    
    
    /**
     * Função que descompacta e lista os arquivos internos.
     * 
     * @param string $link
     */
    private function descompactar($link, $nomeArquivo) 
    {   
        try {
            // Pega o nome da pasta compactada
            $nomePasta = strstr($nomeArquivo, '.', true);

            // Verifica se a extensão zip esta ativada.
            $zip = new ZipArchive();
            if($zip->open($link)) {
                
                $zip->extractTo( strstr($link, $nomeArquivo, true) );
                $zip->close();
                
                $result = array('type'          => 'success', 
                                'result'        => true,
                                'nomePasta'     => $nomePasta);
            } else {
                $result = array('type'          => 'erro', 
                                'result'        => false);
            }
            
        } catch (Exception $exc) {
            $result = array('type'      => 'erro', 
                            'result'    => false,
                            'flashMsg'  => 'O arquivo foi enviado, porém houve falhas ao descompactar o arquivo.');
        }

        return $result;
    }
    
    
    /**
     * Função que irá acessar uma pasta e retornar os arquivos existentes.
     * 
     * @param string $dir
     * @return array $result
     */
    private function listarArquivos($pasta) 
    {
        $arquivos = array();
 
        foreach (new DirectoryIterator($pasta) as $fileInfo) {
            if ($fileInfo->isDot()) {
                continue;
            } elseif ($fileInfo->isDir()) {
                $arquivos['diretorios'][] = utf8_encode($fileInfo->getFilename());
            } elseif ($fileInfo->isFile()) {
                $arquivos['arquivos'][] = utf8_encode($fileInfo->getFilename());
            } else {
                $arquivos['2arquivos'][] = utf8_encode($fileInfo->getFilename());
            }
        }
        
        // Ordena o resultado
        asort($arquivos);
        ksort($arquivos);
        
        return $arquivos;
    }
}



